home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Internet / WWW / gform.1.1 / gform.c < prev    next >
C/C++ Source or Header  |  1996-02-03  |  16KB  |  733 lines

  1. /***
  2.  * gform - A generic HTML form decoder 
  3.  *
  4.  *     It takes a HTML form file and scans
  5.  *    this file for comments beginning with <!--gform ....>
  6.  *    These are taken to be formatting info and delivery commands
  7.  *    for gform.
  8.  *
  9.  *    See gform.txt for description and samples
  10.  *
  11.  *      Swinburne University of Technology and the author will not be 
  12.  *    responsible for any damages or loss suffered or incurred by 
  13.  *    any user or any other person arising in any way from the use
  14.  *    of this software. No warranty of any kind, either express or
  15.  *    implied is given. You may copy, modify and redistribute it.
  16.  *
  17.  *      Ver 1.1e harry@swin.edu.au 8-Nov-95 Swinburne University
  18.  *
  19.  *    Contibutions:
  20.  *        jem@sunsite.unc.edu University of North Caroline   
  21.  *
  22.  *    See CHANGES for change history.
  23.  ***/
  24.  
  25. #include <stdio.h>
  26. #include <sys/types.h>
  27. #include <sys/stat.h>
  28. #include <ctype.h>
  29. #include <time.h>
  30. #include <string.h>
  31.  
  32. #include "config.h"
  33.  
  34. #define bzero(s,n)    memset(s,0,n)
  35. #include <stdlib.h>
  36.  
  37. #define LEN    4096
  38.     
  39. /* keywords for gform */ 
  40. #define DELIVER        "DELIVER"    /* indicates delivery method */
  41. #define MAIL        "MAIL"        /* a delivery method */
  42. #define FFILE        "FILE"        /* a delivery method */
  43. #define PRINT        "PRINT"        /* Send to printer */
  44. #define SUBJECT        "SUBJECT"    /* Subject of mail mesg */
  45. #define REPLY        "REPLY"        /* reply to form submission */
  46. #define GFORM_TAG    "<!GFORM "    /* gform command line keyword */
  47. #define GFORM_TAG2    "<!--GFORM "    /* gform command line keyword */
  48.  
  49. /* commandline parsing states */
  50. #define NSTATE        0    /* NULL state */ 
  51. #define TSTATE        1    /* text string with variables */
  52.  
  53. #define SKIP_WHITE(a)     while (isspace(*a)) a++ 
  54.  
  55. struct entry {
  56.     char *name;
  57.     char *val;
  58.     struct entry *next;
  59. };
  60.  
  61. /* from cgi-bin/util.c */
  62.  
  63. char *fmakeword();
  64. char *makeword();
  65. void unescape_url();
  66. void plustospace();
  67. char *tildeexpand();
  68.  
  69. /* func prototypes */
  70.  
  71. char *decode_commands();
  72. char *command();
  73. void print_header();
  74. char *strnupr();
  75. void error();
  76. char *insert_value();
  77. char *do_escapes();
  78. int send_to_file();
  79. int isendtag();
  80. char *get_html_filename();
  81. char *get_cmd_val();
  82.  
  83. struct     entry *entries, *head;
  84. int     state, linecount, printit=0;
  85. char     *outfile, *address, *subject, DEFSUBJECT[256], 
  86.     *queue, *replyfile, *webhome, date[12], ttime[12];
  87.  
  88. main(argc, argv)
  89. int argc;
  90. char *argv[];
  91. {
  92.      int len,i, line[LEN];
  93.      char s[256], *word, *buf, *tmp, *tmp2, *fname;
  94.      FILE *f1;
  95.  
  96.      setdate(date, ttime);
  97.  
  98.      if (strcmp(getenv("REQUEST_METHOD"),"POST")!=0) 
  99.     error("This program should be referenced with the method=POST\n",0);
  100.      if (strcmp(getenv("CONTENT_TYPE"),
  101.         "application/x-www-form-urlencoded")!=0)
  102.     error("This program can only be used to decode forms\n",0);
  103.  
  104.       
  105.      len = atoi(getenv("CONTENT_LENGTH"));
  106.  
  107.      entries = NULL; replyfile=NULL; 
  108.      outfile = NULL; subject=NULL; address=NULL;
  109.  
  110. /* Get document root directory */
  111.  
  112.     if ((webhome = getenv("DOCUMENT_ROOT"))==NULL) 
  113. #if defined(WEBHOME)
  114.         webhome=WEBHOME;
  115. #endif
  116.     if (webhome==NULL)
  117.         error("Failed to get DOCUMENT_ROOT directory. Define WEBHOME in the config.h file",0);
  118.  
  119. /* Grab all the variable names and data from the form */
  120.  
  121.      for(i=0;len && (!feof(stdin));i++) {
  122.         
  123.     if (entries) { 
  124.         entries->next = (struct entry *) malloc(sizeof(struct entry));
  125.         entries=entries->next;
  126.     } else { 
  127.         entries = (struct entry *) malloc(sizeof(struct entry));
  128.         head = entries;
  129.     }
  130.  
  131. /* stick all the fields of the HTML Form into the entries struct */
  132.  
  133.         entries->val = fmakeword(stdin,'&',&len);
  134.         plustospace(entries->val);
  135.         unescape_url(entries->val);
  136.         word = (char *) makeword(entries->val, '=');
  137.         entries->name = strnupr(word, strlen(word));
  138.  
  139.     entries->next=NULL;
  140.  
  141.      }
  142.  
  143. /* We now have all the data from the form, now decode the 
  144.    'GFORM' commands from the HTML form file */
  145.  
  146.      fname = get_html_filename();
  147.  
  148.      buf = decode_commands(fname);
  149.  
  150.      sprintf(DEFSUBJECT,"Form [%s] submission" ,fname);
  151.  
  152. /* Now deliver the results */
  153.  
  154.      if (outfile)    /* Results to a file */ 
  155.         send_to_file(outfile,buf);
  156.      if (address)     /* or results thru the mail */
  157.         send_email(address,subject,buf);
  158.      if (printit)    /* straight to a printer */
  159.         send_to_printer(queue, buf);
  160.  
  161.      if (replyfile) {    /* The HTML file to reply with */
  162.  
  163. #ifdef USERDIR
  164.         for (tmp2=replyfile; *replyfile=='/'; replyfile++);
  165.         if (*replyfile == '~')  
  166.             tmp2=tildeexpand(replyfile); 
  167.         else {
  168. #endif
  169.             tmp2 = (char *) malloc(strlen(webhome)+strlen(replyfile)+1);
  170.             if (*replyfile=='/') replyfile++;
  171.             sprintf(tmp2,"%s/%s",webhome,replyfile);
  172. #ifdef USERDIR
  173.         }
  174. #endif    
  175.         if ((f1 = fopen(tmp2,"r"))==NULL) {
  176.             sprintf(s,"Opening Replyfile: %s not found",replyfile);
  177.             error(s,0);
  178.         } else {
  179.                 print_header();
  180.             while (fread(line,1,LEN,f1)!=0)
  181.                 fprintf(stdout,"%s",line);
  182.         }
  183.             fclose(f1);        
  184.     } else {    /* A default thank you reply */
  185.         print_header();
  186.         printf("<BODY>");
  187.         printf("<TITLE>Thank you</TITLE>");
  188.         printf("<H3>Thank you</H3>");
  189.         printf("</BODY>");
  190.         }
  191.  
  192.      return(0);
  193. }
  194. /***
  195.  * decode_commands
  196.  *    Read the HTML form file and look for commands 
  197.  *    Replace variables, translate escaped chars
  198.  *    and return the results
  199.  *
  200.  ***/
  201. char *decode_commands(fname)
  202. char *fname;
  203. {
  204.  
  205.      FILE *f1;
  206.      int BRACKET=0,j,escape, vl, variable, endvar=0;
  207.      char line[LEN], *commandline,*start, *end, *trace,
  208.       *word,
  209.       msg[64], tmp[256],
  210.       *buf,        /* The buf of formatted output */ 
  211.       *vp,
  212.       *p,
  213.       ch;
  214.  
  215.      if ((f1 = fopen(fname,"r")) == NULL) {
  216. #ifdef USERDIR
  217.        sprintf(tmp,"File not found: %s",fname); 
  218. #else
  219.        sprintf(tmp,"File not found: %s<BR>('~' expansion not enabled)",fname); 
  220. #endif
  221.  
  222.        error(tmp,0);
  223.  
  224.      }
  225.  
  226.      linecount=0; 
  227.      buf = (char *) malloc(1); 
  228.      *buf=0;
  229.  
  230.      bzero(line, LEN);
  231.  
  232.      while (fgets(line,LEN, f1) !=NULL) {
  233.     linecount++;
  234.     state=NSTATE;
  235.  
  236.     if (!(commandline = command(line))) continue;
  237.  
  238. /* fixup any escaped chars */
  239.  
  240.     commandline = do_escapes(commandline);
  241.  
  242.     SKIP_WHITE(commandline);
  243.  
  244. /* A formatting command line */
  245.  
  246.     if ((state==NSTATE) && (*commandline == '"')) { 
  247.         state = TSTATE;
  248.         start = commandline+1;
  249.         trace=start; end=NULL;
  250.  
  251.         variable=0; escape=0;
  252.         
  253.         for (;*trace && !end;trace++) {
  254.         if (*trace=='"') { 
  255.             end = trace;
  256.             *trace=0;
  257.             if (variable) {
  258.                 variable=0; start=trace;    
  259.                 buf = insert_value(buf,vp,vl);
  260.             } else {
  261.                 buf = (char *) realloc(buf, strlen(buf)+
  262.                 (trace-start)+1);
  263.                 strncat(buf, start , (trace-start));
  264.             }
  265.             state=NSTATE;
  266.             if (BRACKET)
  267.                 error("Missing bracket",linecount);
  268.  
  269.         } else if (variable && *trace == ')') { 
  270.             BRACKET--;     
  271.             endvar=1;    
  272.             vl--;
  273.         } else if (variable) {
  274.             if ((isspace(*trace) || end || endvar) && !BRACKET) {
  275.                 variable=0; start=trace;    
  276.                 buf = insert_value(buf,vp,vl);
  277.                 endvar=0;
  278.             } else
  279.                  vl++;
  280.         } else if (*trace=='$') { 
  281.             variable=1; vl=0;
  282.             vp = trace+1;
  283.             if (*vp == '(') {
  284.                 vp++;
  285.                 BRACKET++;
  286.             }
  287.             buf = (char *) realloc(buf, strlen(buf) + 
  288.                   (trace-start)+1);
  289.             strncat(buf, start , (trace-start));
  290.             start = vp;
  291.         }
  292.  
  293.          }
  294.      }         /* end of formatting command lines */
  295.      else         /* now check command keywords */
  296.           if (state==NSTATE) { 
  297.         if (strcmp(strnupr(commandline,strlen(DELIVER)),
  298.                 DELIVER)==0) {
  299.             commandline=commandline+strlen(DELIVER);
  300.  
  301.             SKIP_WHITE(commandline);
  302.  
  303.             if (*commandline != '=') 
  304.                 error("Missing '='",linecount);
  305.             commandline++;
  306.  
  307.             SKIP_WHITE(commandline);
  308.  
  309. /* Handle the FILE delivery command */
  310.  
  311.             if (strcmp(strnupr(commandline,strlen(FFILE)),FFILE)==0) {
  312.                 commandline=commandline+strlen(FFILE);
  313.  
  314.                 SKIP_WHITE(commandline);
  315.  
  316.                 if (*commandline !='"')
  317.                     error("\" Expected ",linecount);
  318.                 else 
  319.                     outfile=get_cmd_val(commandline);
  320.                 state=NSTATE;
  321.  
  322. /* Handle the PRINT delivery command */
  323.  
  324.             } else if (strcmp(strnupr(commandline,strlen(PRINT)),PRINT)==0) {
  325.                 commandline=commandline+strlen(PRINT);
  326.  
  327.                 SKIP_WHITE(commandline);
  328.  
  329.                 if (isendtag(commandline))
  330.                     queue=0;
  331.                 else if (*commandline !='"')
  332.                     error("\" Expected ",linecount);
  333.                 else
  334.                    queue = get_cmd_val(commandline);
  335.                 printit=1;
  336.                 state=NSTATE;
  337.  
  338. /* Handle the MAIL delivery command */
  339.  
  340.             } else if (strcmp(strnupr(commandline, strlen(MAIL)),MAIL)==0) {
  341.                 commandline=commandline+strlen(MAIL);
  342.  
  343.                 SKIP_WHITE(commandline);
  344.                     
  345.                 if (*commandline!='"')
  346.                     error("\" Expected ",linecount);
  347.                 else {
  348.                    address=get_cmd_val(commandline);
  349.                    commandline+=strlen(commandline)+1;
  350.                 }
  351.                 SKIP_WHITE(commandline);
  352.  
  353.                 if (strcmp(strnupr(commandline,strlen(SUBJECT)),SUBJECT)==0) {
  354.                      commandline=commandline+strlen(SUBJECT);
  355.                      SKIP_WHITE(commandline);
  356.  
  357.                      if (*commandline!='=')
  358.                               error("= Expected",linecount);
  359.                      commandline++;    
  360.  
  361.                      SKIP_WHITE(commandline);
  362.  
  363.                      if (*commandline!='"')
  364.                          error("\" Expected ",linecount);
  365.                      else 
  366.                          subject=get_cmd_val(commandline);
  367.                 } else 
  368.                     subject=DEFSUBJECT;    
  369.                 state=NSTATE;
  370.             } else {
  371.                 sprintf(msg,"Expected %s, %s or %s\n",
  372.                     FFILE, PRINT, MAIL);
  373.                 error(msg, linecount);    
  374.             }
  375. /* Handle REPLY command */
  376.  
  377.             } else if (strcmp(strnupr(commandline,strlen(REPLY)), REPLY)==0) {
  378.                 commandline=commandline+strlen(REPLY);
  379.  
  380.                         SKIP_WHITE(commandline);
  381.         
  382.                 if (*commandline != '=') 
  383.                     error("Missing '='",linecount);
  384.                 commandline++;
  385.  
  386.                         SKIP_WHITE(commandline);
  387.             
  388.                 if (*commandline != '"') 
  389.                     error("\" Expected ",linecount);
  390.                 else 
  391.                     replyfile=get_cmd_val(commandline);
  392.                 state=NSTATE;
  393.             } else
  394.                 error("Commandline syntax, check \"",linecount);
  395.              }
  396.         if (state==TSTATE)
  397.             error("Missing \"",linecount);
  398.  
  399.             bzero(line, LEN);
  400.     } /* end of lines */
  401.     fclose(f1);
  402.  
  403. /* Handle Escaped '$' and '"' that have been turned into
  404.    char 1 and 2 with do_escapes(). Handled last as not to interfere
  405.    with the parsing of commandline
  406. */ 
  407.     for (j=0;j<strlen(buf);j++)
  408.         if (*(buf+j)==1)
  409.             *(buf+j) = '$';
  410.         else if (*(buf+j)==2)
  411.             *(buf+j) = '"';
  412.     return(buf);        
  413. }
  414. /** 
  415.  * insert_value
  416.  *     replace a variable with its value
  417.  *
  418.  **/
  419. char *insert_value(buf, vp, vl)
  420. char *buf, *vp;
  421. int vl;
  422. {
  423.  
  424.     char *word, msg[64], *envvar;
  425.     int hit=0;
  426.  
  427.     word = strnupr(vp,vl);
  428.     entries=head;
  429.     while (entries) {
  430.         if (strcmp(word,entries->name)==0) {
  431.             
  432.             buf = (char *) realloc(buf,strlen(buf) + strlen(entries->val)+4);    /* 3 is to allow for ", " when multiple results */
  433.  
  434.  
  435.                 if (hit) 
  436.             strcat(buf,", ");
  437.  
  438.             strcat(buf,entries->val);
  439.             hit++;
  440.         }
  441.         entries=entries->next;
  442.     }
  443.  
  444. /* if variable is not found in the list of variables, try environement
  445.    variables */
  446.  
  447.     if (!hit) 
  448.         if (strcmp(word, "DATE")==0) {
  449.             buf = (char *) realloc(buf,strlen(buf) +
  450.                  strlen(date)+1);    
  451.             strcat(buf, date);
  452.         } else if (strcmp(word,"TIME")==0) {
  453.             buf = (char *) realloc(buf,strlen(buf) +
  454.                  strlen(ttime)+1);    
  455.             strcat(buf, ttime);
  456.         } else if ((envvar = getenv(word))!=NULL) {
  457.             buf = (char *) realloc(buf,strlen(buf) +
  458.                  strlen(envvar)+1);    
  459.                 strcat(buf, envvar);
  460.         } else {    /* Nothing found */
  461.             buf = (char *) realloc(buf, strlen(buf) + 5);
  462.             strcat(buf,"null");
  463.         }
  464.  
  465.     return(buf);
  466. }
  467.  
  468. /***
  469.  * do_escapes 
  470.  *    Replaces all escaped chars with actual char its escaped.
  471.  *
  472.  ***/
  473.  
  474.  
  475. char* strdup(s)
  476. {
  477.   unsigned long len;
  478.   char* copy = NULL;
  479.   
  480.   if (s == NULL)        /* saftey check to postpone stupid errors */
  481.     return(NULL);
  482.     
  483.   len = strlen(s);        /* length of string - terminator */
  484.   copy = (char*)malloc((size_t)(sizeof(char)*(len + 1)));
  485.   strncpy(copy,s,len + 1);
  486.   return(copy);
  487. }
  488.  
  489.  
  490. char *do_escapes(line)
  491. char *line;
  492. {
  493.  
  494.     char *p, *tmp, *top;
  495.  
  496.     p = strdup(line);
  497.  
  498.     if ((tmp = (char *) malloc(2 * strlen(line)))==NULL)
  499.         return(NULL);
  500.  
  501.     top = tmp;    
  502.     while (*p) {
  503.         if (*p=='\\') {
  504.             p++;
  505.             switch (*p) {
  506.               case 'n' : *p = 10; break;
  507.               case 't' : *p = 8; break;
  508.               case 'r' : *p = 13; break;
  509.               case 'f' : *p = 12; break;
  510.               case '$' : *p = 1; break;   /* special case */
  511.               case '"' : *p = 2; break;   /* special case */
  512.             }
  513.         }
  514.         *(tmp++) = *(p++);
  515.     }    
  516.     return(top);
  517. }
  518.  
  519. /***
  520.  * command
  521.  *    Looks for a 'gform' commandline.
  522.  *    Returns the uppercase commandline (less the leading command tag
  523.  *    or NULL if it is not a commandline.
  524.  *    For backword compatibility, the old GFORM_TAG is still supported
  525.  *    but not really correct.
  526.  *
  527.  ***/
  528. char *command(line)
  529. char *line;
  530. {
  531.  
  532.     char *commandline, *word, *word2;
  533.  
  534.     word = strnupr(line,strlen(GFORM_TAG));
  535.     word2 = strnupr(line,strlen(GFORM_TAG2));
  536.  
  537.     if (strncmp(GFORM_TAG, word,strlen(GFORM_TAG))==0) {
  538.         commandline=line+strlen(GFORM_TAG);
  539.         return(commandline);
  540.     } else if (strncmp(GFORM_TAG2, word2,strlen(GFORM_TAG2))==0) {
  541.         commandline=line+strlen(GFORM_TAG2);
  542.         return(commandline);
  543.     } else
  544.        return(NULL);
  545. }
  546.  
  547. /***
  548.  * send_to_file
  549.  *    Send buffer to a file
  550.  *
  551.  ***/
  552. int send_to_file(fname, buf)
  553. char *fname, *buf;
  554. {
  555.     FILE *f;
  556.  
  557.     if ((f = fopen(fname,"a")) == NULL)
  558.         return(0);
  559.  
  560.     fprintf(f,"%s",buf);
  561.  
  562.     fclose(f);
  563.     return(1);
  564. }
  565.  
  566. /***
  567.  * print_header
  568.  *    Prints the required header for http stuff 
  569.  *
  570.  ***/    
  571. void print_header()
  572. {
  573.  
  574.     printf("Content-type: text/html\n\n");
  575.  
  576.     return;
  577. }
  578. /***
  579.  * strnupr
  580.  *    takes a character string and converts 'len' into
  581.  *    uppercase. It then returns a pointer to the uppercase
  582.  *    chars.
  583.  ***/
  584. char *strnupr(line, len)
  585. char *line;
  586. int len;
  587. {
  588.     int i;
  589.     char *newline;
  590.  
  591.     newline = (char *) malloc(len + 1);
  592.  
  593.     for (i=0;i<len;i++)
  594.         *(newline+i) = toupper(line[i]);        
  595.     *(newline+len) = '\0';
  596.     
  597.     return(newline);
  598. }
  599.  
  600. /***
  601.  * isendtag(cgar *p)
  602.  *    Returns 1 if p is pointing to an end-of-comment tag
  603.  *
  604.  ***/
  605. int isendtag(p)
  606. char *p;
  607. {
  608.     char *q = p;
  609.  
  610.     if (q) {
  611.         if (*q=='-' && q+1 && *(q+1)=='-' && q+2) {
  612.             q+=2;
  613.             SKIP_WHITE(q);    
  614.         }
  615.         if (*q=='>')
  616.             return(1);
  617.     }
  618.     return(0);
  619. }
  620.  
  621. /***
  622.  * get_html_filename()
  623.  *    Returns the filename of the FORM that called us.
  624.  *
  625.  ***/
  626. char *get_html_filename()
  627. {
  628.     static char http[]="HTTP://";
  629.     char *tmp, *path, *p, *uref, *referer = getenv("HTTP_REFERER");
  630.     char s[256];
  631.     struct stat fstat;
  632.  
  633.     if (referer==NULL) {    
  634.         referer=getenv("QUERY_STRING");
  635.         if (referer==NULL)
  636.             error("Could not get environment", 0);
  637.     }
  638.  
  639.     p = referer;
  640.         if (strlen(referer)>6) {
  641.         uref = strnupr(referer,7);
  642.         if (strncmp(http,uref,7)==0) {
  643.             p = referer+7;    
  644.             while (p && *p!='/') p++; /* skip host */
  645.             p++;
  646.         } 
  647.     }
  648.  
  649.     for (tmp=p; *p=='/'; p++);
  650. #ifdef USERDIR
  651.  
  652.     if (*p=='~') {
  653.         tmp=tildeexpand(p);
  654.         if (!tmp) {
  655.             sprintf(s,"Unable to expand: %s",p);    
  656.             error(s,0);
  657.         } else if (stat(tmp,&fstat)) {
  658.             sprintf(s,"File not Found: %s",tmp);
  659.             error(s,0);
  660.         }
  661.         return(tmp);
  662.     } else {
  663. #endif
  664.         path = (char *) malloc(strlen(webhome)+ 
  665.             (tmp==NULL ? 0: strlen(tmp)) + 2);
  666.         sprintf(path, "%s/%s",webhome, tmp);
  667.         return(path);
  668. #ifdef USERDIR
  669.     }
  670. #endif
  671. }
  672.  
  673. /*** 
  674.  * get_cmd_val(string)
  675.  *    Returns a string between quotes , less the quotes
  676.  *
  677.  ***/
  678. char *get_cmd_val(s)
  679. char *s;
  680. {
  681.     char *p;
  682.  
  683.     p = s+1;
  684.     while (*p && *p!='"') p++; 
  685.     if (!*p)
  686.         error("\" Expected ",linecount);
  687.     *p=0;
  688.  
  689.     return(s+1);
  690. }
  691. /***
  692.  * setdate()
  693.  *
  694.  *    Sets 2 variables to the current date and time 
  695.  *
  696.  ***/
  697.  
  698. setdate(date, ttime)
  699. char *date, *ttime;
  700. {
  701.  
  702.     time_t t;    
  703.     struct tm *ttm;
  704.     static char *months[]={"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  705.             "Jul", "Aug","Sep","Oct","Nov","Dec" };
  706.  
  707.     t=time(0);
  708.     ttm = localtime(&t);
  709.  
  710.     sprintf(ttime, "%.2d:%.2d:%.2d",ttm->tm_hour, ttm->tm_min,ttm->tm_sec);
  711.     sprintf(date,"%2d-%s-%2d",ttm->tm_mday, months[ttm->tm_mon],ttm->tm_year);
  712.  
  713. }
  714.  
  715. /***
  716.  * error
  717.  *    Prints a simple error message back to the user 
  718.  *
  719.  ***/
  720. void error(msg, linecount)
  721. char *msg;
  722. int linecount;
  723. {
  724.     print_header();
  725.  
  726.     if (linecount)
  727.         printf("<P>gform: Error (line %d) %s<P>\n",linecount,msg);
  728.     else
  729.         printf("<P>gform: Error %s<P>\n",msg);
  730.  
  731.     exit(1);
  732. }
  733.